
#include "Socket_server.hpp"
#include "Channel_server.hpp"
#include "Coonection_server.hpp"

class Accepter
{
private:
    Socket _socket;   // 创建套接字监听
    EventLoop *_loop; // 对监听套接字进行事件监控
    Channel _channel;

    using AcceptCallback = std::function<void(int)>;

    AcceptCallback _accept_callback;

private:
    void HandleRead()
    {
        int newfd = _socket.Accept();
        if (newfd < 0)
        {
            return;
        }
        if (_accept_callback)
            _accept_callback(newfd);
    }

    int CreateServer(int port)
    {
        bool ret = _socket.CreateServere(port);
        assert(ret == true);

        return _socket.Fd();
    }

public:
    Accepter(EventLoop *loop, int port) : _socket(CreateServer(port)), _loop(loop), _channel(loop, _socket.Fd())
    {
        _channel.SetReadCallback(std::bind(&Accepter::HandleRead, this));
    }
    void SetAcceptCallback(const AcceptCallback &cb)
    {
        _accept_callback = cb;
    }
    void Listen()
    {
        _channel.EanbleRead();
    }
};

class TcpServer
{

private:
    uint64_t _next_id; // 自动增长的连接ID
    int _port;
    int _timeout; // 这个是非活跃链接的统计时长

    bool _enable_inactive_release;

    EventLoop _baseloop;
    Accepter _accepter;
    LoopThreadPool _pool;

    std::unordered_map<uint64_t, PtrConnection> _conns;

    using ConnectionCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;
    using Functor = std::function<void()>;

    ConnectionCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _anyevent_callback;
    ClosedCallback _server_closed_callback;

private:
    void RunAfterInLoop(const Functor &task, int delay)
    {
        _next_id++;
        _baseloop.TimerAdd(_next_id, delay, task);
    }
    void NewConnection(int fd)
    {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));

        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetAnyEventCallback(_anyevent_callback);
        conn->SetSrvClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));

        if (_enable_inactive_release)
            conn->CancelInactiveRelease();

        conn->Established();

        _conns.insert(std::make_pair(_next_id, conn));
    }

    void RemoveConnectionInLoop(const PtrConnection &conn)
    {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end())
        {
            _conns.erase(it);
        }
    }

    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }

public:
    TcpServer(int port) : _port(port),
                          _next_id(0),
                          _enable_inactive_release(false),
                          _accepter(&_baseloop, port),
                          _pool(&_baseloop)
    {

        _accepter.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders :: _1));
        _accepter.Listen();
    }

    void SetThreadCount(int count)
    {
        return _pool.SetThreadCount(count);
    }

    void SetConnectedCallback(const ConnectionCallback &cb)
    {
        _connected_callback = cb;
    }

    void SetMessageCallback(const MessageCallback &cb)
    {
        _message_callback = cb;
    }

    void SetClosedCallback(const ClosedCallback &cb)
    {
        _closed_callback = cb;
    }

    void SetAnyEventCallback(const AnyEventCallback &cb)
    {
        _anyevent_callback = cb;
    }

    void SetSrvClosedCallback(const ClosedCallback &cb)
    {
        _server_closed_callback = cb;
    }

    void EnableInactiveRelease(int timeout)
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }

    void RunAfter(const Functor &task, int delay)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }

    void Start()
    {
        _pool.Create();
        _baseloop.Start();
    }
};